<template>
  <div class="fbx-container">
    <div ref="canvasContainer" class="canvas-container"></div>
    <div v-if="isLoading" class="loading">加载中...</div>
    <div v-if="errorMsg" class="error">{{ errorMsg }}</div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watchEffect } from "vue";
import * as THREE from "three";
import { FBXLoader } from "three/addons/loaders/FBXLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

// 响应式状态（仅用于模板展示）
const canvasContainer = ref(null);
const isLoading = ref(true);
const errorMsg = ref("");

// 关键修改：Three.js核心对象用普通变量存储，不使用ref
let scene = null;
let camera = null;
let renderer = null;
let controls = null;
let animationId = null;

// 初始化场景（使用普通变量）
const initThreeScene = () => {
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xf0f0f0);

  camera = new THREE.PerspectiveCamera(
    75,
    canvasContainer.value.clientWidth / canvasContainer.value.clientHeight,
    0.1,
    1000
  );
  camera.position.z = 5;

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(
    canvasContainer.value.clientWidth,
    canvasContainer.value.clientHeight
  );
  canvasContainer.value.appendChild(renderer.domElement);

  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;

  // 添加光源
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
  directionalLight.position.set(5, 5, 5);
  scene.add(directionalLight);
};

// 加载FBX模型
const loadFbxModel = () => {
  const loader = new FBXLoader();

  loader.load(
    "/example.fbx", // 模型路径（根据实际位置调整）
    (object) => {
      scene.add(object);

      // 模型缩放和定位
      object.scale.set(0.01, 0.01, 0.01);
      object.position.set(0, 0, 0);

      // 自动调整相机位置
      const box = new THREE.Box3().setFromObject(object);
      const center = box.getCenter(new THREE.Vector3());
      const size = box.getSize(new THREE.Vector3());
      const maxDim = Math.max(size.x, size.y, size.z);
      const fov = camera.fov * (Math.PI / 180);
      const cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2)) * 1.5;

      camera.position.z = cameraZ;
      camera.lookAt(center);
      controls.target.copy(center);

      isLoading.value = false;
    },
    (xhr) => {
      console.log(`加载进度: ${Math.round((xhr.loaded / xhr.total) * 100)}%`);
    },
    (error) => {
      console.error("加载失败:", error);
      errorMsg.value = "模型加载失败，请检查文件路径";
      isLoading.value = false;
    }
  );
};

// 动画循环
const animate = () => {
  animationId = requestAnimationFrame(animate);
  controls?.update();
  renderer?.render(scene, camera);
};

// 窗口大小调整
const handleResize = () => {
  if (!camera || !renderer || !canvasContainer.value) return;

  const width = canvasContainer.value.clientWidth;
  const height = canvasContainer.value.clientHeight;

  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
};

// 生命周期
onMounted(() => {
  if (canvasContainer.value) {
    initThreeScene();
    loadFbxModel();
    animate();
    window.addEventListener("resize", handleResize);
  }
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
  if (animationId) cancelAnimationFrame(animationId);
  if (renderer) renderer.dispose();
  if (controls) controls.dispose();

  // 清空场景
  if (scene) {
    while (scene.children.length > 0) {
      scene.remove(scene.children[0]);
    }
  }
});

// 监听容器大小变化
watchEffect(() => {
  if (canvasContainer.value) {
    handleResize();
  }
});
</script>

<style scoped>
.fbx-container {
  width: 100%;
  height: 80vh;
  position: relative;
  border: 1px solid #eee;
  border-radius: 8px;
  overflow: hidden;
}

.canvas-container {
  width: 100%;
  height: 100%;
}

.loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 18px;
  color: #666;
}

.error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #ff4d4f;
  font-size: 16px;
}
</style>
